<?php

class TFsBOXSession extends TFsBOXDebugger
	{
		const ADMIN = 1;
		const MODERATOR = 2;
		const REGULAR = 3;

		static $PathInfo;

		static protected $form_position = "bottom";
		static private $logged_in = NULL;
		static private $session_id;
		static protected $user_errors = array();
		static $user_info;
		static protected $user_name;
		static protected $user_notices = array();
		static protected $user_shout;
		static protected $user_site;

		function __construct()
			{
				$this->site_url = TFsBOX::$Config->value("site_url",
														 "http://". $_SERVER['SERVER_NAME'] ."/");

				self::$PathInfo = array_values(array_filter(explode("/", $_SERVER['PATH_INFO'])));
			}

		function currentShout()
			{
				return self::$user_shout;
			}

		function currentShoutPage()
			{
				if (count(self::$PathInfo) > 0)
				{
					if (self::$PathInfo[0] == "tfsbox")
					{
						if (self::$PathInfo[1] == "page")
							return (int) self::$PathInfo[2];

						else if (self::$PathInfo[1] == "cpanel")
						{
							if (self::$PathInfo[2] == "page")
								return (int) self::$PathInfo[3];
						}

						else if (self::$PathInfo[1] == "shouts")
						{
							if (self::$PathInfo[2] == "page")
								return (int) self::$PathInfo[3];
						}
					}
				}

				return 1;
			}

		function endSession()
			{
				self::unsetCookie('tfsbox_username');
				self::unsetCookie('tfsbox_userid');
				if (!TFsBOX::$Database->databaseMode())
					unset($_SESSION['tfsbox_sessid']);
				else
					self::unsetCookie('tfsbox_sessid');

				TFsBOX::redirect($_SERVER['SCRIPT_NAME']);
			}

		function errors()
			{
				return self::$user_errors;
			}

		function formPosition()
			{
				// Flatfile
				if (!TFsBOX::$Database->databaseMode())
					return TFsBOX::$Config->value("form_position", "bottom");
				// MySQL
				else
					return self::$form_position;
			}

		function hasErrors()
			{
				return (bool) count(self::$user_errors);
			}

		function hasNotices()
			{
				return (bool) count(self::$user_notices);
			}

		function hasShout()
			{
				return (isset(self::$user_shout)
					 && !empty(self::$user_shout));
			}

		function hasShoutReady()
			{
				return ($this->hasUsername()
					&& $this->hasShout()
					&& !$this->hasErrors());
			}

		function hasUsername()
			{
				return (isset(self::$user_name)
					 && !empty(self::$user_name));
			}

		function hasUserSite()
			{
				return (isset(self::$user_site)
					 && !empty(self::$user_site));
			}

		static function ip()
			{
				return $_SERVER['REMOTE_ADDR'];
			}

		function isShoutValid($shout)
			{
				if (isset($shout))
				{
					if (empty($shout))
						self::storeError("No message provided&mdash;what's a shout without a shout?");

					else return true;
				}

				return false;
			}

		function isUsernameValid($username)
			{
				if (isset($username))
				{
					if (!empty($username))
					{
						if (preg_match(TFsBOX::NameRegex, $username))
						{
							if (strlen($username) < (TFsBOX::$Config->value("name_length", 25) + 1))
								return true;

							else self::storeError("The name you provided is too long, it must be no bigger than ". TFsBOX::$Config->value("name_length", 25) ." characters.");
						}

						else self::storeError("The name provided contains special characters.");
					}

					else self::storeError("You provided an empty name; you must provide a name.");
				}

				return false;
			}

		function isUserSiteValid($site)
			{
				if (!empty($site)
				 && $_POST['tfsbox_site'] != "http://")
				{
					if (preg_match(TFsBOX::SiteRegex, $_POST['tfsbox_site'])
					 && !TFsBOX::$Database->isUrlBanned($_POST['tfsbox_site']))
						return true;
					else
						self::storeNotice('Invalid URL provided: reverting to default URL.');
				}

				return false;
			}

		function loggedIn()
			{
				if (TFsBOX::$Database->isIpBanned(self::ip()))
					return false;

				if (self::$logged_in)
					return self::$logged_in;

				// Flatfile
				if (!TFsBOX::$Database->databaseMode()
				 && isset($_SESSION['tfsbox_sessid']))
				{
					return self::$logged_in = (bool) ($_SESSION['tfsbox_sessid']
													  == $_COOKIE['tfsbox_userid']);
				}

				else if (TFsBOX::$Database->databaseConnection()
					  && isset($_COOKIE['tfsbox_userid']))
				{
					// MySQL
					if (TFsBOX::$Database->databaseMode()
					 == TFsBOXDatabase::MYSQL)
					{
						self::$user_info = TFsBOX::$Database->userInfo($_COOKIE['tfsbox_userid']);
						if (!self::$user_info)
							return false;

						return self::$logged_in = (bool) (self::$user_info->auth_token
														  == self::sessionHash());
					}
				}

				return false;
			}

		function notices()
			{
				return self::$user_notices;
			}

		static function randomSessionHash()
			{
				$hash = "";

				for ($i = 1; strlen($hash) < 64; $i++)
				{
					$arr = range(0, (8 * $i), (4 * $i));
					shuffle($arr);
					$hash .= implode($arr);
				}

				return sha1($hash);
			}

		static function sessionHash($include_sessid = true)
			{
				$username = (isset($_POST['tfsbox_username'])) ? $_POST['tfsbox_username'] : "";
				$username = (isset($_COOKIE['tfsbox_username'])) ? $_COOKIE['tfsbox_username'] : $username;

				$sess_id = (isset($_COOKIE['tfsbox_sessid']) && $include_sessid) ? $_COOKIE['tfsbox_sessid'] : "";

				return $sess_id
					 . sha1(md5($username)
						  . md5(self::ip())
						  . md5(self::userAgent()));
			}

		static function setCookie($cookie_name, $cookie_value)
			{
				setcookie($cookie_name, $cookie_value, mktime(date('H'), date('i'), date('s'), date('m'), date('d') + 14, date('Y')), "/");
			}

		function startSession()
			{
				// Check user name
				if ($this->isUsernameValid($_POST['tfsbox_name']))
					self::$user_name = $_POST['tfsbox_name'];

				// Check shout
				if ($this->isShoutValid($_POST['tfsbox_shout']))
					self::$user_shout = TFsBOX::filterShout($_POST['tfsbox_shout']);

				// Check user site
				if ($this->isUserSiteValid($_POST['tfsbox_site']))
					self::$user_site = $_POST['tfsbox_site'];
				else if ($_POST['tfsbox_site'] == '$_SERVER[\'REQUEST_URI\']')
					self::$user_site = $_SERVER['REQUEST_URI'];

				// Flatfile
				if (!TFsBOX::$Database->databaseMode())
				{
					if (session_start())
					{
						if ($this->loggedIn())
						{
							self::$user_name = TFsBOX::USERNAME;
							self::$user_site = TFsBOX_SITE;
						}
					}

					else self::storeError("Session failed to start.");
				}

				else if (TFsBOX::$Database->databaseConnection())
				{
					// MySQL
					if (TFsBOX::$Database->databaseMode()
					 == TFsBOXDatabase::MYSQL)
					{
						if ($this->loggedIn()) // make sure $user_info gets filled
						{
							self::$user_name = self::$user_info->username;
							self::$user_site = self::$user_info->site;
						}

						else if (TFsBOX::$Database->guestsAllowed())
							self::$user_name = "Guest_". ip2long(self::ip());
					}
				}
			}

		static function storeError($error)
			{
				if (!in_array($error, self::$user_errors))
					self::$user_errors[] = $error;
			}

		static function storeNotice($notice)
			{
				if (!in_array($notice, self::$user_notices))
					self::$user_notices[] = $notice;
			}

		static function unsetCookie($cookie_name)
			{
				setcookie($cookie_name, '', mktime(date('H'), date('i'), date('s'), date('m')-1, date('d'), date('Y')), "/");
			}

		static function urlRoot()
			{
				$dir = (isset($_SERVER['SUBDOMAIN_DOCUMENT_ROOT']))
					 ? $_SERVER['SUBDOMAIN_DOCUMENT_ROOT']
					 : $_SERVER['DOCUMENT_ROOT'];

				// Remove any slash at the end just in case
				$strlen = strlen($dir) - 1;

				if ($dir[$strlen] == "/"
				 xor $dir[$strlen] == "\\")
					$dir[$strlen] = "";

				return str_replace($dir, "", dirname(__FILE__));
			}

		static function userAgent()
			{
				return $_SERVER['HTTP_USER_AGENT'];
			}

		function username()
			{
				return self::$user_name;
			}

		function userId()
			{
				return (self::$user_info->id) ? self::$user_info->id : 0;
			}

		function userRanking()
		{
			if (self::$logged_in)
			{
				// Flatfile
				if (!TFsBOX::$Database->databaseMode())
					return TFsBOXSession::ADMIN;

				else
				{
					if (!self::$user_info->ranking)
						self::$user_info->ranking = TFsBOXSession::REGULAR;

					return self::$user_info->ranking;
				}
			}

			return TFsBOXSession::REGULAR;
		}

		function userSubscriptions()
			{
				return (self::$user_info->subscriptions) ? explode("\n", self::$user_info->subscriptions) : array();
			}

		function userSite()
			{
				if ($this->hasUserSite())
					return self::$user_site;
				else
					return "http://". $_SERVER['SERVER_NAME'] ."/";
			}
	}

?>
